
package com.sausageking.server;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Days;

import com.googlecode.objectify.NotFoundException;
import com.sausageking.client.ConsumerService.AuthType;
import com.sausageking.server.common.BCrypt;
import com.sausageking.server.dao.GenericDao;
import com.sausageking.shared.Consumer;
import com.sausageking.shared.Merchant;

public class AuthManagerImpl implements AuthManager {

  public boolean authenticate(AuthType authType, String email, String secret) {
    if (authType.equals(AuthType.PASSWORD)) {
      GenericDao<Consumer> dao = new GenericDao<Consumer>(Consumer.class);
      Consumer user;
      try {
        user = dao.get(email);
      } catch (NotFoundException e) {
        return false;
      }
      return BCrypt.checkpw(secret, user.getPassword());
    } else {
      return false; // TODO: implement token based auth
    }
  }

  @Override
  public String hashPassword(String password) {
    return BCrypt.hashpw(password, BCrypt.gensalt());
  }

  @Override
  public boolean hasPassword(String email) {
    GenericDao<Consumer> dao = new GenericDao<Consumer>(Consumer.class);
    try {
      Consumer user = dao.get(email);
      return (user.getPassword() != null);
    } catch (NotFoundException e) {
      return false;
    }
  }

  @Override
  public String getPurcaseConfirmationCode(Merchant merchant, DateTime date) {
    DateTimeZone timeZone = DateTimeZone.forID(merchant.getTimeZoneId());
    int daysSince1999 = Days.daysBetween(
        new DateTime(1999, 1, 1, 0, 0, timeZone), date).getDays();
    String data = String.format("%d%d%s", daysSince1999, merchant.getId(),
        merchant.getSalt());
    try {
      MessageDigest md = MessageDigest.getInstance("SHA-1");
      md.update(data.getBytes());
      byte[] aMessageDigest = md.digest();
      BigInteger n = new BigInteger(aMessageDigest);
      return String.format("%03d", Math.abs(n.intValue() % 1000));
    } catch (NoSuchAlgorithmException e) {
      return "";
    }
  }

  @Override
  public boolean validatePurchaseConfirmationCode(Merchant merchant,
      DateTime date, String code) {
    return getPurcaseConfirmationCode(merchant, date).equals(code);
  }
}
